package filetime

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// DemoFileOperations 演示文件的基本操作
func DemoFileOperations() {
	fmt.Println("=== 文件和时间操作演示 ===")
	fmt.Println("\n--- 文件基本操作 ---")

	// 1. 创建文件
	fileName := "sample.txt"
	file, err := os.Create(fileName)
	if err != nil {
		fmt.Printf("创建文件失败: %v\n", err)
		return
	}
	defer file.Close()
	fmt.Printf("成功创建文件: %s\n", fileName)

	// 2. 写入文件
	data := "Hello, Go!\n这是一个文件操作示例。\n今天是个好日子。\n"
	n, err := file.WriteString(data)
	if err != nil {
		fmt.Printf("写入文件失败: %v\n", err)
		return
	}
	fmt.Printf("成功写入%d字节到文件\n", n)

	// 3. 关闭并重新打开文件（读取模式）
	file.Close()
	readFile, err := os.Open(fileName)
	if err != nil {
		fmt.Printf("打开文件失败: %v\n", err)
		return
	}
	defer readFile.Close()

	// 4. 读取整个文件
	content, err := io.ReadAll(readFile)
	if err != nil {
		fmt.Printf("读取文件失败: %v\n", err)
		return
	}
	fmt.Printf("文件内容:\n%s\n", string(content))

	// 5. 按行读取文件
	readFile.Seek(0, 0) // 重置文件指针到开头
	scanner := bufio.NewScanner(readFile)
	fmt.Println("按行读取文件:")
	lineNum := 1
	for scanner.Scan() {
		fmt.Printf("行 %d: %s\n", lineNum, scanner.Text())
		lineNum++
	}

	if scanErr := scanner.Err(); scanErr != nil {
		fmt.Printf("扫描文件错误: %v\n", err)
	}

	// 6. 追加内容到文件
	appendFile, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Printf("打开文件追加内容失败: %v\n", err)
		return
	}
	defer appendFile.Close()

	appendData := "这是追加的内容。\nGo语言文件操作很简单！\n"
	n, err = appendFile.WriteString(appendData)
	if err != nil {
		fmt.Printf("追加内容失败: %v\n", err)
		return
	}
	fmt.Printf("成功追加%d字节到文件\n", n)

	// 7. 获取文件信息
	fileInfo, err := os.Stat(fileName)
	if err != nil {
		fmt.Printf("获取文件信息失败: %v\n", err)
		return
	}

	fmt.Printf("文件信息:\n")
	fmt.Printf("  名称: %s\n", fileInfo.Name())
	fmt.Printf("  大小: %d字节\n", fileInfo.Size())
	fmt.Printf("  修改时间: %v\n", fileInfo.ModTime())
	fmt.Printf("  是否为目录: %v\n", fileInfo.IsDir())
	fmt.Printf("  权限: %v\n", fileInfo.Mode())

	// 8. 删除文件
	// 注意：为了演示，我们不实际删除文件，而是输出一条消息
	fmt.Printf("演示删除文件: %s\n", fileName)
	// 取消下面的注释以实际删除文件
	// if err := os.Remove(fileName); err != nil {
	//	fmt.Printf("删除文件失败: %v\n", err)
	//	return
	// }
	// fmt.Printf("成功删除文件: %s\n", fileName)
}

// DemoDirectoryOperations 演示目录操作
func DemoDirectoryOperations() {
	fmt.Println("\n--- 目录操作 ---")

	// 1. 创建目录
	dirName := "demo_dir"
	err := os.Mkdir(dirName, 0755)
	if err != nil {
		fmt.Printf("创建目录失败: %v\n", err)
	} else {
		fmt.Printf("成功创建目录: %s\n", dirName)
	}

	// 2. 创建多级目录
	multiDirName := "parent/child/grandchild"
	err = os.MkdirAll(multiDirName, 0755)
	if err != nil {
		fmt.Printf("创建多级目录失败: %v\n", err)
	} else {
		fmt.Printf("成功创建多级目录: %s\n", multiDirName)
	}

	// 3. 列出目录内容
	entries, err := os.ReadDir(".")
	if err != nil {
		fmt.Printf("读取目录内容失败: %v\n", err)
		return
	}

	fmt.Println("当前目录内容:")
	for _, entry := range entries {
		if entry.IsDir() {
			fmt.Printf("[目录] %s\n", entry.Name())
		} else {
			fmt.Printf("[文件] %s\n", entry.Name())
		}
	}

	// 4. 遍历目录树（使用filepath.Walk）
	fmt.Println("\n遍历当前目录树:")
	err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		indent := strings.Repeat("  ", len(strings.Split(path, string(os.PathSeparator)))-1)
		if info.IsDir() {
			fmt.Printf("%s[目录] %s\n", indent, info.Name())
		} else {
			fmt.Printf("%s[文件] %s (大小: %d字节)\n", indent, info.Name(), info.Size())
		}
		return nil
	})

	if err != nil {
		fmt.Printf("遍历目录树失败: %v\n", err)
	}

	// 5. 删除目录
	// 注意：为了演示，我们不实际删除目录，而是输出一条消息
	fmt.Printf("演示删除目录: %s\n", dirName)
	// 取消下面的注释以实际删除目录
	// if err := os.Remove(dirName); err != nil {
	//	fmt.Printf("删除目录失败: %v\n", err)
	// }
	// fmt.Printf("成功删除目录: %s\n", dirName)

	// 6. 删除多级目录
	fmt.Printf("演示删除多级目录: %s\n", "parent")
	// 取消下面的注释以实际删除多级目录
	// if err := os.RemoveAll("parent"); err != nil {
	//	fmt.Printf("删除多级目录失败: %v\n", err)
	// }
	// fmt.Printf("成功删除多级目录: parent\n")
}

// DemoTimeOperations 演示时间和日期操作
func DemoTimeOperations() {
	fmt.Println("\n--- 时间和日期操作 ---")

	// 1. 获取当前时间
	now := time.Now()
	fmt.Printf("当前时间: %v\n", now)

	// 2. 格式化时间
	// Go的时间格式化使用固定的参考时间: Mon Jan 2 15:04:05 MST 2006
	formatted := now.Format("2006-01-02 15:04:05")
	fmt.Printf("格式化时间: %s\n", formatted)

	// 3. 解析字符串为时间
	timeStr := "2023-12-25 10:00:00"
	parsedTime, err := time.Parse("2006-01-02 15:04:05", timeStr)
	if err != nil {
		fmt.Printf("解析时间失败: %v\n", err)
	} else {
		fmt.Printf("解析的时间: %v\n", parsedTime)
	}

	// 4. 时间组件
	year := now.Year()		// 年
	month := now.Month()	// 月
	day := now.Day()		// 日
	hour := now.Hour()		// 时
	minute := now.Minute()	// 分
	second := now.Second()	// 秒
	nanosecond := now.Nanosecond() // 纳秒
	weekday := now.Weekday()	// 星期几

	fmt.Printf("时间组件: %d-%d-%d %d:%d:%d.%d, %v\n", year, month, day, hour, minute, second, nanosecond, weekday)

	// 5. 时间计算
	// 添加时间
	later := now.Add(24 * time.Hour) // 24小时后
	fmt.Printf("24小时后: %v\n", later)

	enxtWeek := now.AddDate(0, 0, 7) // 一周后
	fmt.Printf("一周后: %v\n", enxtWeek)

	// 时间差
	duration := enxtWeek.Sub(now)
	fmt.Printf("时间差: %v\n", duration)

	// 计算两个时间之间的天数差
	daysDiff := int(duration.Hours() / 24)
	fmt.Printf("天数差: %d天\n", daysDiff)

	// 6. 定时器
	fmt.Println("等待2秒...")
	timer := time.NewTimer(2 * time.Second)
	<-timer.C
	fmt.Println("2秒已过！")

	// 7. 休眠
	fmt.Println("休眠1秒...")
	time.Sleep(1 * time.Second)
	fmt.Println("1秒已过！")

	// 8. 时区
	// 加载指定时区
	loc, err := time.LoadLocation("America/New_York")
	if err != nil {
		fmt.Printf("加载时区失败: %v\n", err)
	} else {
		nyTime := now.In(loc)
		fmt.Printf("纽约时间: %v\n", nyTime)
	}

	// 9. Unix时间戳
	unixTime := now.Unix()       // 秒级时间戳
	unixNano := now.UnixNano()   // 纳秒级时间戳
	fmt.Printf("Unix时间戳(秒): %d\n", unixTime)
	fmt.Printf("Unix时间戳(纳秒): %d\n", unixNano)

	// 从时间戳创建时间
	timeFromUnix := time.Unix(unixTime, 0)
	fmt.Printf("从时间戳恢复的时间: %v\n", timeFromUnix)
}

// DemoFileAndTimeOperations 展示文件和时间操作
func DemoFileAndTimeOperations() {
	// 调用各个演示函数
	DemoFileOperations()
	DemoDirectoryOperations()
	DemoTimeOperations()
}